package juego;
import java.util.ArrayList;
import java.util.Iterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public abstract class Vehiculo extends Automata {
	
	//Atributos de instancia
	protected boolean esGuia;
	protected boolean huyendo;
	protected Energia resistencia;
	
	
	//Metodos
	
	//Constructor. recibe una coordenada y un entero
	public Vehiculo(Coordenada coordenada, int vida){
		super(coordenada);
		this.esGuia = false;
		this.huyendo = false;
		this.resistencia = new Energia(vida);
	};
	
	//Transforma al vehiculo en guia
	public void designarGuia(){
		esGuia = true;
	};
	
	public void emprenderHuida(){
		huyendo = true;
	};
	
	@Override
	public boolean esNaveEnemiga(){
		return true;
	};
	
	@Override
	public boolean esProyectil(){
		return false;
	};
	
	protected abstract int puntajePorDestruccion();
	
	protected abstract int velocidad();
	
	//Mueve el vehiculo hacia arriba
	protected void huir(){
		ubicacion.moverEnY(-this.velocidad());
	};
	
	//Le indica a todas las naves que deben huir
	protected void provocarHuida(ArrayList<Movil> listaDeObjetos){
		
		Iterator<Movil> iterador = listaDeObjetos.iterator();
		while (iterador.hasNext()){
			Movil movil = iterador.next();
			if (movil.esNaveEnemiga()){
				
				//lo casteo
				Vehiculo nave = (Vehiculo) movil;
				nave.emprenderHuida();
			};
		};
	};
	
	@Override
	//se elimina de la lista si corresponde. devuelve el puntaje
	public int recibirImpacto(Impacto impacto, ArrayList<Movil> listaDeMoviles, ArrayList<Botin> listaDeBotines){
		impacto.herir(this.resistencia);
		int puntaje = this.verificarDestruccion(listaDeMoviles, listaDeBotines);
		return puntaje;
	}
		
		
	//Lo primero que hace el vehiculo es moverse. Luego verifica si fue impactado,
	//y actua en consecuencia.	
	@Override
	public int vivir(ArrayList<Movil> listaDeMoviles, ArrayList<Botin> listaDeBotines){
		int puntaje = 0;
		//movimiento
		if (this.huyendo){
			this.huir();
			puntaje = this.impactar(listaDeMoviles,listaDeBotines);
		}
		else{
			this.movimientoPropio();
			if (this.EstaFueraDelEscenario(this.ubicacion)){
				this.destruirse(listaDeMoviles);
			}else{
				//impacto
				puntaje = this.impactar(listaDeMoviles,listaDeBotines);
			}
		}
		return puntaje;
	};
	
	
	
	//retorna 0. resuelve el choque
	protected int impactoPropio(Movil movil, ArrayList<Movil> listaDeMoviles, ArrayList<Botin> listaDeBotines){
		//solo puede ser impactado por el algo42 o proyectiles de este
		if (movil.verLealtad()){
			//movil hiere a this
			movil.impactoProvocado().herir(this.resistencia);
			//movil recibe el impacto. se elimina de la lista si corresponde
			movil.recibirImpacto(this.impactoProvocado(), listaDeMoviles, listaDeBotines);
			//nada con lo que pueda impactar modificara el puntaje
		}
		return 0;
	}
	
	//se encarga de destruirse si corresponde. devuelve el puntaje
	protected int verificarDestruccion(ArrayList<Movil> listaDeMoviles, ArrayList<Botin> listaDeBotines){
		//si queda energia no se destruye y retorna 0
		if(this.resistencia.quedaEnergia()){
			return 0;
		}
		//si se destruye retorna el puntaje x destruccion
		this.destruirse(listaDeMoviles);
		if (this.esGuia){
			this.provocarHuida(listaDeMoviles);
		}
		return this.puntajePorDestruccion();
	}
	
	private void persistirEsGuia(Document doc, Element elemento) {
		Boolean valorEsGuia = new Boolean(this.esGuia);
		Element esGuia = doc.createElement("EsGuia");
		elemento.appendChild(esGuia);
		esGuia.setTextContent(valorEsGuia.toString());
	}
	
	private void persistirHuyendo(Document doc, Element elemento) {
		Boolean valorHuyendo = new Boolean(this.huyendo);
		Element huyendo = doc.createElement("Huyendo");
		elemento.appendChild(huyendo);
		huyendo.setTextContent(valorHuyendo.toString());
	}
	
	private void persistirResistencia(Document doc, Element elemento) {
		Element resistencia = this.resistencia.getElement(doc);
		elemento.appendChild(resistencia);
	}
	
	protected void persistirVehiculo(Document doc, Element elemento) {
		this.persistirEsGuia(doc, elemento);
		this.persistirHuyendo(doc, elemento);
		this.persistirResistencia(doc, elemento);
		this.persistirAutomata(doc, elemento);
	}

	public static void recuperarVehiculo(Element element, Vehiculo vehiculo) {
		recuperarPropios(element, vehiculo);
		Automata.recuperarAutomata(element, vehiculo);
	}
	
	
	private static void recuperarPropios(Element element, Vehiculo vehiculo) {
		NodeList childs = element.getChildNodes();
		for (int i = 0; i < childs.getLength(); i++) {
			Node child = childs.item(i);
			if (child.getNodeName().equals("EsGuia")) {
				vehiculo.esGuia = Boolean.parseBoolean(child.getTextContent());
			} 
			else if (child.getNodeName().equals("Huyendo")) {
				vehiculo.huyendo = Boolean.parseBoolean(child.getTextContent());
			} 
			else if (child.getNodeName().equals("Energia")) {
				vehiculo.resistencia = Energia.fromElement((Element) child);
			} 
		}
		
	}
	
	

			
		
	
		
	
		
	
	

}



